package com.zb.factory.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zb.constant.FinanceConstant;
import com.zb.constant.WorkConstant;
import com.zb.entity.*;
import com.zb.excel.converter.WorkConverter;
import com.zb.extend.FactoryRechargeExtend;
import com.zb.extend.WorkFeeDetailExtend;
import com.zb.extend.WorkOrderExtend;
import com.zb.factory.service.ConFactoryService;
import com.zb.result.PageUtil;
import com.zb.service.*;
import com.zb.view.ViewNetworkEmpAccount;
import com.zb.vo.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author WEN
 * @Date 2024/2/28 0028
 **/
@Service
public class ConFactoryServiceImpl implements ConFactoryService {
    @Resource
    private ZjFactoryService factoryService;
    @Resource
    private ZjFactoryAccountBalanceService factoryAccountBalanceService;
    @Resource
    private ZjFactoryOrderModuleSettlementService factoryOrderModuleSettlementService;
    @Resource
    private ZjWorkModuleService workModuleService;
    @Resource
    private ZjWorkOrderService workOrderService;
    @Resource
    private ZjAccountService accountService;
    @Resource
    private ZjWorkFeeService workFeeService;
    @Resource
    private ZjWorkSpareService workSpareService;
    @Resource
    private ZjNetworkService networkService;
    @Resource
    private ViewNetworkEmpAccountService viewNetworkEmpAccountService;
    @Resource
    private ZjFactoryStrategyService factoryStrategyService;
    @Resource
    private ZjFactoryRechargeService factoryRechargeService;
    @Resource
    private ZjFactoryRechargeVoucherService factoryRechargeVoucherService;

    // 获取商家详情之结算价
    @Override
    public Map<String, Object> getFactoryOrderModuleSettlementList(Long factoryId, PageUtil pageUtil) {
        QueryWrapper<ZjFactoryOrderModuleSettlement> orderModuleSettlementQueryWrapper = new QueryWrapper<>();
        orderModuleSettlementQueryWrapper.select("id", "module_id", "price", "is_all_inclusive_fee AS allInclusiveFee", "gmt_create", "gmt_update")
                .eq("factory_id", factoryId)
                .orderByDesc("gmt_update");
        PageUtil.setPageLimit(pageUtil);
        Page<ZjFactoryOrderModuleSettlement> page = factoryOrderModuleSettlementService.page(new Page<>(pageUtil.getPage(), pageUtil.getLimit()), orderModuleSettlementQueryWrapper);
        if (CollectionUtil.isEmpty(page.getRecords())) {
            return PageUtil.pageList(page.getCurrent(), page.getSize(), page.getTotal(), new ArrayList<>());
        }
        QueryWrapper<ZjWorkModule> moduleQueryWrapper = new QueryWrapper<>();
        moduleQueryWrapper.select("id", "type", "name", "out_sourcing_price")
                .in("id", page.getRecords().stream().map(ZjFactoryOrderModuleSettlement::getModuleId).toList());
        List<ZjWorkModule> moduleList = workModuleService.list(moduleQueryWrapper);
        return PageUtil.pageList(page.getCurrent(), page.getSize(), page.getTotal(), page.getRecords().stream().map(settlement -> {
            FactoryOrderModuleSettlementListVo vo = new FactoryOrderModuleSettlementListVo();
            BeanUtil.copyProperties(settlement, vo);
            vo.setCreateTime(settlement.getGmtCreate());
            vo.setUpdateTime(settlement.getGmtUpdate());
            moduleList.stream().filter(f -> Objects.equals(f.getId(), settlement.getModuleId())).findFirst().ifPresent(module -> {
                vo.setType(WorkConverter.moduleTypeConverter(module.getType()));
                vo.setModule(module.getName());
                vo.setModulePrice(module.getOutSourcingPrice());
            });
            return vo;
        }).toList());
    }

    // 获取商家详情之工单列表
    @Override
    public Map<String, Object> getFactoryDetailOrderList(Long factoryId, PageUtil pageUtil) {
        PageUtil.setPageLimit(pageUtil);
        long count = workOrderService.getFactoryDetailOrderListCount(factoryId);
        if (count <= 0) {
            return PageUtil.pageList(pageUtil.getPage(), pageUtil.getLimit(), count, new ArrayList<>());
        }
        List<WorkOrderExtend> orderExtends = workOrderService.getFactoryDetailOrderList(factoryId, pageUtil);
        // 获取服务商
        List<ZjNetwork> networkList = new ArrayList<>();
        List<Long> networkIds = orderExtends.stream().filter(f -> null != f.getNetworkId() && f.getNetworkId() > 0).map(WorkOrderExtend::getNetworkId).distinct().toList();
        if (CollectionUtil.isNotEmpty(networkIds)) {
            networkList.addAll(networkService.getNameByIds(networkIds));
        }
        List<Long> networkEmpIds = orderExtends.stream().filter(f -> null != f.getNetworkEmpId() && f.getNetworkEmpId() > 0).map(WorkOrderExtend::getNetworkEmpId).distinct().toList();
        List<ViewNetworkEmpAccount> empAccountList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(networkEmpIds)) {
            empAccountList.addAll(viewNetworkEmpAccountService.getByIds(networkEmpIds));
        }
        List<FactoryDetailOrderListVo> voList = orderExtends.stream().map(order -> {
            FactoryDetailOrderListVo vo = new FactoryDetailOrderListVo();
            BeanUtil.copyProperties(order, vo);
            vo.setWorkNo(order.getCode());
            vo.setCreateTime(order.getGmtCreate());
            vo.setUpdateTime(order.getGmtUpdate());
            networkList.stream().filter(f -> Objects.equals(f.getId(), order.getNetworkId())).findFirst().map(ZjNetwork::getName).ifPresent(vo::setNetwork);
            empAccountList.stream().filter(f -> Objects.equals(f.getId(), order.getNetworkEmpId())).findFirst().ifPresent(networkEmp -> {
                vo.setEngineer(networkEmp.getName());
                vo.setEngineerPhone(networkEmp.getPhone());
            });
            return vo;
        }).toList();
        return PageUtil.pageList(pageUtil.getPage(), pageUtil.getLimit(), count, voList);
    }

    // 获取商家详情之工单费用列表
    @Override
    public Map<String, Object> getFactoryDetailOrderFeeList(Long factoryId, PageUtil pageUtil) {
        return workFeeService.getFactoryDetailOrderFeeList(factoryId, pageUtil);
    }

    // 删除商家
    @Override
    public void deleteBatchByIds(List<Long> factoryIds) {
        if (CollectionUtil.isEmpty(factoryIds)) {
            return;
        }
        // todo 删除商家
    }

    // 根据品牌商家ID获取商家详情
    @Override
    public FactoryDetailVo getFactoryDetail(Long id) {
        ZjFactory factory = factoryService.getById(id);
        Assert.notNull(factory, "商家参数[ " + id + " ]的数据不存在");
        FactoryDetailVo vo = new FactoryDetailVo();
        BeanUtil.copyProperties(factory, vo);
        ZjFactoryAccountBalance balance = factoryAccountBalanceService.getById(id);
        vo.setMoney(balance.getMoney());
        vo.setFreezeMoney(balance.getFreezeMoney());
        QueryWrapper<ZjWorkOrder> orderQueryWrapper = new QueryWrapper<>();
        orderQueryWrapper.select("id", "status", "settlement_status")
                        .eq("factory_id", id);
        List<ZjWorkOrder> orderList = workOrderService.list(orderQueryWrapper);
        vo.setTotalOrderCount(orderList.stream().count());
        vo.setHandlerOrderCount(orderList.stream().filter(f -> f.getStatus() == WorkConstant.WORK_STATUS_3).count());
        vo.setWaitSettlementOrderCount(orderList.stream().filter(f -> f.getSettlementStatus() == WorkConstant.WORK_SETTLEMENT_STATUS_1).count());
        vo.setOrderFeeCount(workFeeService.getFactoryDetailOrderFeeListCount(id));
        vo.setOrderSpareCount(workSpareService.getFactoryDetailOrderSpareListCount(id));
        vo.setSettlementType(factoryStrategyService.getSettlementType(id));
        return vo;
    }

    // 获取品牌商家列表
    @Override
    public Map<String, Object> getList(Long custAccId, FactoryListSelectVo selectVo) {
        PageUtil.setPageLimit(selectVo);
        long count = factoryService.getListCount(custAccId, selectVo);
        if (count <= 0) {
            return PageUtil.pageList(selectVo.getPage(), selectVo.getLimit(), count, new ArrayList<>());
        }
        List<ZjFactory> factoryList = factoryService.getList(custAccId, selectVo);
        List<ZjFactoryStrategy> factoryStrategies = factoryStrategyService.getByIds(factoryList.stream().map(ZjFactory::getId).toList());
        List<ZjFactoryAccountBalance> accountBalances = factoryAccountBalanceService.getByIds(factoryList.stream().map(ZjFactory::getId).toList());
        return PageUtil.pageList(selectVo.getPage(), selectVo.getLimit(), count, factoryList.stream().map(factory -> {
            FactoryListVo vo = new FactoryListVo();
            BeanUtil.copyProperties(factory, vo);
            vo.setCreateTime(factory.getGmtCreate());
            vo.setUpdateTime(factory.getGmtUpdate());
            vo.setSettlementTypeStr(factoryStrategies.stream().filter(f -> Objects.equals(f.getId(), factory.getId())).findFirst().map(strategy -> {
                return strategy.getSettlementType() == 1? "预充值" : "月结";
            }).orElse("预充值"));
            vo.setOrderableMoney(accountBalances.stream().filter(f -> Objects.equals(f.getId(), factory.getId())).findFirst().map(account -> {
                return account.getMoney().subtract(account.getFreezeMoney());
            }).orElse(new BigDecimal("0.0")));
            return vo;
        }).toList());
    }

    // 获取商家充值审核表
    @Override
    public Map<String, Object> getFactoryRechargeCheckList(Long custAccId, FactoryRechargeCheckListSearchVo search) {
        PageUtil.setPageLimit(search);
        long count = factoryRechargeService.getFactoryRechargeCheckListCount(custAccId, search);
        if (count <= 0) {
            return PageUtil.pageList(search.getPage(), search.getLimit(), count, new ArrayList<>());
        }
        List<FactoryRechargeExtend> factoryRechargeExtends = factoryRechargeService.getFactoryRechargeCheckList(custAccId, search);
        List<ZjFactoryRechargeVoucher> rechargeVouchers = factoryRechargeVoucherService.getByFactoryRechargeIds(factoryRechargeExtends.stream().map(FactoryRechargeExtend::getId).toList());
        return PageUtil.pageList(search.getPage(), search.getLimit(), count, factoryRechargeExtends.stream().map(recharge -> {
            FactoryRechargeCheckListVo vo = new FactoryRechargeCheckListVo();
            BeanUtil.copyProperties(recharge, vo);
            vo.setImage(rechargeVouchers.stream().filter(f -> Objects.equals(f.getFactoryRechargeId(), recharge.getId())).findFirst().map(ZjFactoryRechargeVoucher::getImage).orElse(""));
            vo.setCreateTime(recharge.getGmtCreate());
            vo.setUpdateTime(recharge.getGmtUpdate());
            return vo;
        }));
    }

    // 审核商家充值
    @Override
    @Transactional
    public void checkFactoryRecharge(CheckFactoryRechargeVo rechargeVo) {
        QueryWrapper<ZjFactoryRecharge> wrapper = new QueryWrapper<>();
        wrapper.select("id", "factory_id", "code", "status", "money")
                .in("id", rechargeVo.getIds());
        List<ZjFactoryRecharge> factoryRechargeList = factoryRechargeService.list(wrapper);
        Assert.notEmpty(factoryRechargeList, "您审核的充值单不存在，请检查！");
        List<Long> rechargeIds = rechargeVo.getIds().stream().filter(f -> factoryRechargeList.stream().noneMatch(f2 -> Objects.equals(f2.getId(), f))).toList();
        Assert.isTrue(CollectionUtil.isEmpty(rechargeIds), "您审核的充值单不存在：" + rechargeIds.stream().map(String::valueOf).collect(Collectors.joining("、")));
        List<String> codes = factoryRechargeList.stream().filter(f -> f.getStatus() != 1).map(ZjFactoryRecharge::getCode).toList();
        Assert.isTrue(CollectionUtil.isEmpty(codes), "您审核的充值单已审核或已取消，不允许重复操作，充值单号：" + String.join("、", codes));
        List<ZjFactoryRecharge> rechargeList = new ArrayList<>();
        ZjFactoryRecharge recharge = null;
        for (Long id : rechargeVo.getIds()) {
            recharge = new ZjFactoryRecharge();
            recharge.setId(id);
            recharge.setStatus(rechargeVo.getCheckResult() == 1? 2 : 4);
            recharge.setPaymentTime(new Date());
            rechargeList.add(recharge);
        }
        if (rechargeVo.getCheckResult() == 1) {
            QueryWrapper<ZjFactoryAccountBalance> accountBalanceQueryWrapper = new QueryWrapper<>();
            accountBalanceQueryWrapper.select("id", "money")
                    .in("id", factoryRechargeList.stream().map(ZjFactoryRecharge::getFactoryId).distinct().toList());
            List<ZjFactoryAccountBalance> balanceList = factoryAccountBalanceService.list(accountBalanceQueryWrapper);
            balanceList.forEach(t -> {
                t.setMoney(t.getMoney().add(factoryRechargeList.stream().filter(f -> Objects.equals(f.getFactoryId(), t.getId()))
                        .map(ZjFactoryRecharge::getMoney).reduce(BigDecimal::add).orElse(new BigDecimal("0.0"))));
            });
            factoryAccountBalanceService.updateBatchById(balanceList);
        }
    }


}
